package org.tool.spring.application;

import cn.hutool.core.util.ObjectUtil;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * ApplicationContext 相关工具类
 *
 * @author 李坤
 * @date 2022/7/7 17:12
 */
@Component
public class ApplicationContextUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    /**
     * 设置ApplicationContext
     *
     * @param applicationContext 上下文
     *
     * @throws BeansException 相关异常信息
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtil.applicationContext = applicationContext;
    }

    /**
     * 根据类型获取Spring Bean对象
     *
     * @param beanName bean 名称
     *
     * @return Spring Bean
     */
    public static Object getBean(String beanName) {
        return ObjectUtil.isNotNull(applicationContext) ? applicationContext.getBean(beanName) : null;
    }

    /**
     * 根据类型获取Spring Bean对象
     *
     * @param tClass 对象类型
     * @param <T>    类型
     *
     * @return Spring Bean
     */
    public static <T> T getBean(Class<T> tClass) {
        return ObjectUtil.isNotNull(applicationContext) ? applicationContext.getBean(tClass) : null;
    }

    /**
     * 根据名称和类型获取Spring Bean对象
     *
     * @param beanName bean 名称
     * @param tClass   对象类型
     * @param <T>      类型
     *
     * @return Spring Bean
     */
    public static <T> T getBean(String beanName, Class<T> tClass) {
        return ObjectUtil.isNotNull(applicationContext) ? applicationContext.getBean(beanName, tClass) : null;
    }

    /**
     * 获得List集合形式指定接口实现类
     *
     * @param tClass 指定接口实现类型
     *
     * @return 查询结果
     */
    public static <T> List<T> getRealizeBeanList(Class<T> tClass) {
        return ObjectUtil.isNotNull(applicationContext) ? new ArrayList<>(getRealizeBeans(tClass).values()) : Collections.emptyList();
    }

    /**
     * 获得 Map 集合形式指定接口实现类
     *
     * @param tClass 指定接口实现类型
     *
     * @return 查询结果
     */
    public static <T> Map<String, T> getRealizeBeans(Class<T> tClass) {
        return ObjectUtil.isNotNull(applicationContext) ? applicationContext.getBeansOfType(tClass) : Collections.emptyMap();
    }

    /**
     * 获取被指定注解标注的spring bean
     *
     * @param annotation 指定注解
     *
     * @return spring bean
     *
     * @throws BeansException 相关异常信息
     */
    public static Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotation) throws BeansException {
        return ObjectUtil.isNotNull(applicationContext) ? applicationContext.getBeansWithAnnotation(annotation) : Collections.emptyMap();
    }

}
